home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / pcmagazi / 1992 / 11 / rdump / rdump.c < prev    next >
C/C++ Source or Header  |  1992-02-17  |  5KB  |  175 lines

  1. /*--------------------------------------
  2.    RDUMP.C -- RIFF Dumper for DOS
  3.               (c) Charles Petzold, 1992
  4.   --------------------------------------*/
  5.  
  6. #include <stdio.h>
  7. #include <string.h>
  8.  
  9. typedef unsigned int BOOL ;
  10.  
  11. #define TRUE   1
  12. #define FALSE  0
  13.  
  14. #define min(a,b) ((a) < (b) ? (a) : (b))
  15.  
  16. #define HIWORD(l) ((unsigned int) ((l) >> 16))
  17. #define LOWORD(l) ((unsigned int) ((l) & 65535))
  18.  
  19. long DumpChunk (FILE * file, BOOL bWithinInfoForm, int iLevel)
  20.      {
  21.      static char szBuffer [4096] ;
  22.      BOOL        bRiffChunk, bListChunk, bInfoForm ;
  23.      char        szChunkType [5], szFormType [5] ;
  24.      int         i, iReadBytes ;
  25.      long        lChunkSize, lChunkSizeFile, lFilePos1, lFilePos2, lBytesRead ;
  26.  
  27.                // Get the file position to later calculate number of bytes read
  28.  
  29.      fgetpos (file, &lFilePos1) ;
  30.  
  31.                // Read the chunk type and verify that it's in a correct format
  32.  
  33.      if (fread (szChunkType, 1, 4, file) != 4)
  34.           return 0 ;
  35.  
  36.      szChunkType [4] = '\0' ;
  37.  
  38.      if (strlen (szChunkType) < 4)
  39.           return 0 ;
  40.  
  41.                // Set Boolean values if the chunk type if "RIFF" or "LIST"
  42.  
  43.      bRiffChunk = strcmp (szChunkType, "RIFF") == 0 ? TRUE : FALSE ;
  44.      bListChunk = strcmp (szChunkType, "LIST") == 0 ? TRUE : FALSE ;
  45.  
  46.      if (iLevel == 0 && !bRiffChunk)
  47.           return 0 ;
  48.  
  49.                // Read the chunk size, and display the type and size
  50.  
  51.      if (fread (&lChunkSize, 1, 4, file) != 4)
  52.           return 0 ;
  53.  
  54.      printf ("%.*s%s %04X-%04X", iLevel + 1, "\t\t\t\t", szChunkType,
  55.                                  HIWORD (lChunkSize), LOWORD (lChunkSize)) ;
  56.  
  57.      if (bRiffChunk == 1 || bListChunk == 1)
  58.           {
  59.                     // For a RIFF or LIST, read the form type
  60.  
  61.           if (fread (szFormType, 1, 4, file) != 4)
  62.                {
  63.                printf ("\n") ;
  64.                return 0 ;
  65.                }
  66.  
  67.           szFormType [4] = '\0' ;
  68.  
  69.           if (strlen (szFormType) < 4)
  70.                return 0 ;
  71.  
  72.                     // Set Boolean value if form type is "INFO", and print it
  73.  
  74.           bInfoForm = strcmp (szFormType, "INFO") == 0 ? bListChunk : FALSE ;
  75.  
  76.           printf (" %s\n", szFormType) ;
  77.  
  78.           lChunkSize -= 4 ;
  79.  
  80.                     // Recursively dump the chunks
  81.  
  82.           while (lChunkSize > 0)
  83.                {
  84.                if (0 == (lBytesRead = DumpChunk (file, bInfoForm, iLevel + 1)))
  85.                     return 0 ;
  86.  
  87.                lChunkSize -= lBytesRead ;
  88.  
  89.                if (lChunkSize < 0)
  90.                     return 0 ;
  91.                }
  92.           }
  93.      else
  94.           {
  95.                     // If it's not a RIFF or LIST, find the chunk size
  96.  
  97.           lChunkSizeFile = ~1 & (lChunkSize + 1) ;
  98.  
  99.           iReadBytes = (int) (min (lChunkSizeFile, sizeof (szBuffer))) ;
  100.  
  101.           if ((int) fread (szBuffer, 1, iReadBytes, file) != iReadBytes)
  102.                return 0 ;
  103.  
  104.                     // Display the first 24 characters of an INFO
  105.                     // string or the first 8 bytes of binary data
  106.  
  107.           if (bWithinInfoForm)
  108.                printf (" \"%.24s\"%s\n", szBuffer,
  109.                        lChunkSize > (long) 25 ? " ..." : "") ;
  110.           else
  111.                {
  112.                for (i = 0 ; i < min (8, lChunkSize) ; i++)
  113.                     printf (" %02X", (unsigned char) szBuffer [i]) ;
  114.  
  115.                printf ("%s\n", lChunkSize > (long) 8 ? " ..." : "") ;
  116.                }
  117.  
  118.           lChunkSizeFile -= iReadBytes ;
  119.  
  120.                     // Continue reading the chunk until it's exhausted
  121.  
  122.           while (lChunkSizeFile > 0)
  123.                {
  124.                iReadBytes = (int) (min (lChunkSizeFile, sizeof (szBuffer))) ;
  125.  
  126.                if ((int) fread (szBuffer, 1, iReadBytes, file) != iReadBytes)
  127.                     return 0 ;
  128.  
  129.                lChunkSizeFile -= iReadBytes ;
  130.                }
  131.           }
  132.  
  133.                // Determine how many bytes have been read, and return them
  134.  
  135.      fgetpos (file, &lFilePos2) ;
  136.  
  137.      return lFilePos2 - lFilePos1 ;
  138.      }
  139.  
  140. int main (int argc, char * argv [])
  141.      {
  142.      FILE * file ;
  143.      int    i ;
  144.  
  145.                // Syntax message if no filenames on command line
  146.  
  147.      if (argc < 2)
  148.           {
  149.           fprintf (stderr, "Syntax: RDUMP [filename...]") ;
  150.           return 1 ;
  151.           }
  152.  
  153.                // For each filename, display the name and call DumpChunk
  154.  
  155.      for (i = 1 ; i < argc ; i++)
  156.           {
  157.           printf ("\n%s\n\n", argv [i]) ;
  158.  
  159.           if (NULL == (file = fopen (argv [i], "rb")))
  160.                {
  161.                fprintf (stderr, "\n\tCannot open file.\n", argv [i]) ;
  162.                fclose (file) ;
  163.                continue ;
  164.                }
  165.  
  166.           if (0 == DumpChunk (file, FALSE, 0))
  167.                fprintf (stderr, "\n\tFile has incorrect format.\n",
  168.                                 argv [i]) ;
  169.  
  170.           fclose (file) ;
  171.           }
  172.  
  173.      return 0 ;
  174.      }
  175.